package com.santoker.user.service.util;

import java.math.BigDecimal;

/**
 * 计算火力工具
 *
 * @author jiangs
 */
public class CalcFirepowerUtil {

    /**
     * 获取当前豆温差值
     *
     * @param X  当前豆温
     * @param X1 背景曲线当前豆温
     * @return
     */
    public static BigDecimal getΔX(BigDecimal X, BigDecimal X1) {
        return X.subtract(X1);
    }

    /**
     * 获取5秒前豆温差值
     *
     * @param X5  5秒前豆温
     * @param X15 5秒前背景曲线豆温
     * @return
     */
    public static BigDecimal getΔX5(BigDecimal X5, BigDecimal X15) {
        return X5.subtract(X15);
    }

    /**
     * 获取火力积分调整值
     *
     * @param ΔX  当前豆温差值
     * @param ΔX5 5秒前豆温差值
     * @param ΔJ1 1秒前的火力积分调整值
     * @return
     */
    public static BigDecimal getΔJ(BigDecimal ΔX, BigDecimal ΔX5, BigDecimal ΔJ1) {
        BigDecimal a = ΔX5.subtract(ΔX);
        BigDecimal b = ΔX.abs();
        BigDecimal c = a.divide(ΔX, 2, BigDecimal.ROUND_HALF_UP);
        final BigDecimal k_1 = new BigDecimal("1");
        final BigDecimal _k_1 = new BigDecimal("-1");
        final BigDecimal k_02 = new BigDecimal("0.2");
        final BigDecimal k_05 = new BigDecimal("0.5");
        final BigDecimal _k_05 = new BigDecimal("-0.5");

        // ΔX5-ΔX > 0.5
        if (a.compareTo(k_05) == 1) {
            // |ΔX| <= 0.5
            if (b.compareTo(k_05) <= 0) {
                return ΔJ1;
            }
            // 1 > ΔX > 0.5
            if (ΔX.compareTo(k_05) == 1 && ΔX.compareTo(k_1) == -1) {
                // 0.5 < ΔX5-ΔX <= 1 温差缩小合适
                if (a.compareTo(k_1) <= 0) {
                    return ΔJ1;
                }
                // ΔX5-ΔX > 1 温差在缩小速度过快
                else {
                    // ΔJ=ΔJ1+0.2*ΔX/|ΔX|
                    return getΔJ(ΔX, ΔJ1, true, k_02);
                }
            }
            // ΔX > 1
            else if (ΔX.compareTo(k_1) == 1) {
                // 0.5 <= (ΔX5-ΔX)/ΔX <= 1 温差在缩小速度合适
                if (c.compareTo(k_05) >= 0 && c.compareTo(k_1) <= 0) {
                    return ΔJ1;
                }
                // 1 < (ΔX5-ΔX)/ΔX 温差缩小过快
                else if (c.compareTo(k_1) == 1) {
                    // ΔJ=ΔJ1+0.2*ΔX/|ΔX|
                    return getΔJ(ΔX, ΔJ1, true, k_02);
                }
                // (ΔX5-ΔX)/ΔX < 0.5 温差在缩小速度过慢
                else {
                    // ΔJ=ΔJ1-0.2*ΔX/|ΔX|
                    return getΔJ(ΔX, ΔJ1, false, k_02);
                }
            }
            // ΔX < -1
            else if (ΔX.compareTo(k_1) == 1) {
                // ΔJ=ΔJ1-ΔX/|ΔX| 温差在扩大 改为 ΔJ=ΔJ1-0.2*ΔX/|ΔX|
                return getΔJ(ΔX, ΔJ1, false, k_02);
            }
            // -1 < ΔX < -0.5
            else {
                // ΔJ=ΔJ1-0.5*ΔX/|ΔX| 温差在扩大 改为 ΔJ=ΔJ1-0.2*ΔX/|ΔX|
                return getΔJ(ΔX, ΔJ1, false, k_02);
            }
        }
        // ΔX5-ΔX < -0.5
        else if (a.compareTo(_k_05) == -1) {
            // |ΔX| <= 0.5
            if (b.compareTo(k_05) <= 0) {
                return ΔJ1;
            }
            // 1 > ΔX > 0.5
            else if (ΔX.compareTo(k_05) == 1 && ΔX.compareTo(k_1) == -1) {
                // ΔJ=ΔJ1-0.5*ΔX/|ΔX| 温差在扩大 改为 ΔJ=ΔJ1-0.2*ΔX/|ΔX|
                return getΔJ(ΔX, ΔJ1, false, k_02);
            }
            // ΔX > 1
            else if (ΔX.compareTo(k_1) == 1) {
                // ΔJ=ΔJ1-ΔX/|ΔX| 温差在扩大 改为 ΔJ=ΔJ1-0.2*ΔX/|ΔX|
                return getΔJ(ΔX, ΔJ1, false, k_02);
            }
            // ΔX < -1
            else if (ΔX.compareTo(_k_1) == -1) {
                // 0.5 <= (ΔX5-ΔX)/ΔX <= 1 温差在缩小速度合适
                if (c.compareTo(k_05) >= 0 && c.compareTo(k_1) <= 0) {
                    return ΔJ1;
                }
                // 1 < (ΔX5-ΔX)/ΔX 温差缩小过快
                else if (c.compareTo(k_05) >= 0 && c.compareTo(k_1) <= 0) {
                    // ΔJ=ΔJ1+0.2*ΔX/|ΔX|
                    return getΔJ(ΔX, ΔJ1, true, k_02);
                }
                // (ΔX5-ΔX)/ΔX < 0.5 温差在缩小速度过慢
                else {
                    // ΔJ=ΔJ1-0.2*ΔX/|ΔX|
                    return getΔJ(ΔX, ΔJ1, false, k_02);
                }
            }
            // -1 < ΔX < -0.5
            else {
                // -1 <= ΔX5-ΔX < -0.5 温差缩小合适
                if (a.compareTo(_k_1) >= 0) {
                    return ΔJ1;
                }
                // ΔX5-ΔX < -1 温差在缩小速度过快
                else {
                    // ΔJ=ΔJ1+0.2*ΔX/|ΔX|
                    return getΔJ(ΔX, ΔJ1, true, k_02);
                }
            }
        }
        // 0 <= ΔX5-ΔX <= 0.5
        else if (a.compareTo(k_1) >= 0 && a.compareTo(k_05) <= 0) {
            // |ΔX| <= 0.5
            if (b.compareTo(k_05) <= 0) {
                return ΔJ1;
            }
            // 1 > ΔX > 0.5
            else if (ΔX.compareTo(k_05) == 1 && ΔX.compareTo(k_1) == -1) {
                // ΔJ=ΔJ1-0.2*ΔX/|ΔX|
                return getΔJ(ΔX, ΔJ1, false, k_02);
            }
            // ΔX > 1
            else if (ΔX.compareTo(k_1) == 1) {
                // ΔJ=ΔJ1-ΔX/|ΔX| 温差在缩小速度过慢
                return getΔJ(ΔX, ΔJ1, false, k_1);
            }
            // ΔX < -1
            else if (ΔX.compareTo(_k_1) == -1) {
                // ΔJ=ΔJ1-ΔX/|ΔX| 温差在扩大 改为 ΔJ=ΔJ1-0.2*ΔX/|ΔX|
                return getΔJ(ΔX, ΔJ1, false, k_02);
            }
            // -1 < ΔX < -0.5
            else {
                // ΔJ=ΔJ1-0.5*ΔX/|ΔX| 温差在扩大 改为 ΔJ=ΔJ1-0.2*ΔX/|ΔX|
                return getΔJ(ΔX, ΔJ1, false, k_02);
            }
        }
        // -0.5 <= ΔX5-ΔX < 0
        else {
            // |ΔX| <= 0.5
            if (b.compareTo(k_05) <= 0) {
                return ΔJ1;
            }
            // 1 > ΔX > 0.5
            else if (ΔX.compareTo(k_05) == 1 && ΔX.compareTo(k_1) == -1) {
                // ΔJ=ΔJ1-0.5*ΔX/|ΔX| 改为 ΔJ=ΔJ1-0.2*ΔX/|ΔX|
                return getΔJ(ΔX, ΔJ1, false, k_02);
            }
            // ΔX > 1
            else if (ΔX.compareTo(k_1) == 1) {
                // ΔJ=ΔJ1-ΔX/|ΔX| 温差在缩小速度过慢 改为 ΔJ=ΔJ1-0.2*ΔX/|ΔX|
                return getΔJ(ΔX, ΔJ1, false, k_02);
            }
            // ΔX < -1
            else if (ΔX.compareTo(_k_1) == -1) {
                // ΔJ=ΔJ1-ΔX/|ΔX| 温差在缩小
                return getΔJ(ΔX, ΔJ1, false, k_1);
            }
            // -1 < ΔX < -0.5
            else {
                // ΔJ=ΔJ1-0.2*ΔX/|ΔX|
                return getΔJ(ΔX, ΔJ1, true, k_02);
            }
        }
    }

    /**
     * 获取火力积分调整值
     *
     * @param ΔX       当前豆温差值
     * @param ΔJ1      1秒前的火力积分调整值
     * @param isAdd    是否相加：false减，true加
     * @param multiple 倍数
     * @return
     */
    private static BigDecimal getΔJ(BigDecimal ΔX, BigDecimal ΔJ1, boolean isAdd, BigDecimal multiple) {
        // ΔJ=ΔJ1-ΔX/|ΔX|
        BigDecimal divide = ΔX.divide(ΔX.abs(), 2, BigDecimal.ROUND_HALF_UP);
        BigDecimal multiply = multiple.multiply(divide);
        if (isAdd) {
            return ΔJ1.add(multiply).setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        return ΔJ1.subtract(multiply).setScale(2, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 获取实际执行火力
     *
     * @param Y  背景曲线火力
     * @param ΔJ 火力积分调整值
     * @return
     */
    public static BigDecimal getQ(BigDecimal Y, BigDecimal ΔJ) {
        return Y.add(ΔJ).setScale(2, BigDecimal.ROUND_HALF_UP);
    }

}
